﻿using Colorful.Models;
using Colorful.CMS.Core;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Colorful.Database;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Colorful;

#region HttpContext
namespace Colorful
{
    public static class HttpExtension
    {
        private delegate object CreateObject();
        private static Dictionary<Type, CreateObject> _constrcache = new Dictionary<Type, CreateObject>();

        #region IFormFile
        public static void SaveAs(this IFormFile file, string savePath)
        {
            using (var fileStream = new FileStream(savePath, FileMode.Create))
            {
                file.CopyTo(fileStream);
            }
        }
        #endregion

        #region HttpRequest
        public static string GetDomainUrl(this HttpRequest request)
        {
            return $"{request.Scheme}://{request.Host}";
        }
        public static Uri GetUri(this HttpRequest request)
        {
            return new Uri($"{request.Scheme}://{request.Host}{request.Path.Value}{(request.QueryString.HasValue ? request.QueryString.Value : "")}");
        }
        public static string GetPathAndQuery(this HttpRequest request)
        {
            return $"{request.Path.Value}{(request.QueryString.HasValue ? request.QueryString.Value : "")}";
        }
        public static string GetEncodedUrl(this HttpRequest request)
        {
            return System.Net.WebUtility.UrlEncode(request.GetUri().ToString());
        }
        public static string Get(this HttpRequest request, string key)
        {
            if (request.Method == "GET")
            {
                return request.Query[key];
            }
            else if (request.Method == "POST")
                return request.Form[key];
            return null;
        }
        /// <summary>
        /// UserAgent
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static string GetUA(this HttpRequest request)
        {
            return $"{request.Headers["User-Agent"]}";
        }
        #endregion

        #region HttpContext

        #region MapPath
        public static string MapPath(this HttpContext context, string url)
        {
            if (!url.StartsWith("/"))
                throw new InvalidException("无效的路径！");
            var staticFolders = WebConfig.WebStaticFolders;
            if (staticFolders.Any(a => url.StartsWith("/" + a, StringComparison.OrdinalIgnoreCase)))
                url = "/wwwroot" + url;
            var rootPath = WebConfig.RootPath;
            var path = rootPath + url.Replace("/", "\\");
            return path;
        }
        #endregion

        #region 日志
        public static ILogger GetLogger(this HttpContext context, string category = null)
        {
            if (category == null)
                category = context.Request.GetPathAndQuery();
            var logger = (ILogger)context.Items["Logger"];
            if (logger == null)
            {
                var loggerFactory = context.RequestServices.GetService<ILoggerFactory>();
                logger = loggerFactory.CreateLogger(category);
                context.Items["Logger"] = logger;
            }
            return logger;
        }
        public static void WriteDebug(this HttpContext context, string message, string category = null)
        {
            var logger = context.GetLogger(category);
            logger.LogDebug(message);
        }
        public static void WriteWarn(this HttpContext context, string message, string category = null)
        {
            var logger = context.GetLogger(category);
            logger.LogWarning("◆◆◆" + message);
        }
        public static void WriteLog(this HttpContext context, string message, string category = null)
        {
            var logger = context.GetLogger(category);
            logger.LogInformation(message);
        }
        public static void WriteError(this HttpContext context, Exception ex, string message, string category = null)
        {
            var logger = context.GetLogger(category);
            logger.LogError(ex, message);
        }
        public static void WriteError(this HttpContext context, Exception ex, string category = null)
        {
            var logger = context.GetLogger(category);
            logger.LogError(ex, "错误");
        }
        #endregion

        #region Cookie操作
        public static void SetCookie(this HttpContext context, string key, string value, DateTime? expires = null)
        {
            context.SetCookie(key, value, false, expires);
        }
        private static void SetCookie(this HttpContext context, string key, string value, bool encrypt, DateTime? expires = null)
        {
            if (encrypt)
                value = AESHelper.Encrypt(value);
            context.Response.Cookies.Append(key, value, new CookieOptions()
            {
                Expires = expires == null ? DateTime.Now.AddDays(360) : expires.Value
            });
        }
        public static void SetEncryptCookie(this HttpContext context, string key, string value, DateTime? expires = null)
        {
            context.SetCookie(key, value, true, expires);
        }
        public static string GetCookies(this HttpContext context, string key, bool encrypt = false)
        {
            string value;
            context.Request.Cookies.TryGetValue(key, out value);
            if (!string.IsNullOrEmpty(value) && encrypt)
            {
                value = AESHelper.Decrypt(value);
            }
            return value;
        }
        public static void RemoveCookie(this HttpContext context, string key)
        {
            context.Response.Cookies.Delete(key, new CookieOptions() { Expires = DateTime.Now.AddDays(-1) });
        }
        #endregion

        #region 获取IP
        public static string GetIP(this HttpContext context)
        {
            if (context == null)
                return "";
            string ip = context.Connection.RemoteIpAddress.ToString();
            if (string.IsNullOrEmpty(ip))
            {
                if (!string.IsNullOrEmpty(context.Request.Headers["HTTP_X_FORWARDED_FOR"]))
                {
                    ip = context.Request.Headers["HTTP_X_FORWARDED_FOR"].ToString();
                }
                else if (!string.IsNullOrEmpty(context.Request.Headers["HTTP_X_REAL_IP"]))
                    ip = context.Request.Headers["HTTP_X_REAL_IP"].ToString();
                else
                {
                    ip = context.Request.Headers["REMOTE_ADDR"].ToString();
                }
            }
            if (ip == "::1")
                ip = "127.0.0.1";
            return ip;
        }
        #endregion

        #endregion
    }
}
#endregion

#region System.Web
namespace System.Web
{
    public static class HttpContext
    {
        private static IHttpContextAccessor _contextAccessor;

        public static Microsoft.AspNetCore.Http.HttpContext Current => _contextAccessor.HttpContext;

        internal static void Configure(IHttpContextAccessor contextAccessor)
        {
            _contextAccessor = contextAccessor;
        }
    }

    #region Extensions
    public static class StaticHttpContextExtensions
    {
        public static void AddHttpContextAccessor(this IServiceCollection services)
        {
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        }

        public static IApplicationBuilder UseStaticHttpContext(this IApplicationBuilder app)
        {
            var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
            System.Web.HttpContext.Configure(httpContextAccessor);
            return app;
        }
    }
    #endregion
}

#endregion


